package markov;

import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;

import bnetwork.ClimateNetwork;
import bnetwork.Node;

import everything.WorldMap;

public class CopyOfMDPState {
	public static final int NORTH = -1;
	public static final int SOUTH = -2;
	public static final int EAST = -3;
	public static final int WEST = -4;
	public static final int NO_DIRECTION = -5;
	private static final double RewardF = 10;
	private static final double CostM = -5;
	private static final double CostS = -10;
	boolean[] flags;
	int xPosition;
	int yPosition;
	int direction;
	Map<Node, Integer> evidence;

	ClimateNetwork n;

	public CopyOfMDPState(boolean[] flags, int xPosition, int yPosition, int direction, Map<Node, Integer> evidence, ClimateNetwork n) {
		this.flags = flags;
		this.xPosition = xPosition;
		this.yPosition = yPosition;
		this.direction = direction;
		this.evidence = evidence;
		this.n = n;
	}

	public Map<CopyOfMDPState, Double> nextState(int action, WorldMap map){
		Map<CopyOfMDPState, Double> ans = new HashMap<CopyOfMDPState, Double>();

		double reward = CostM;
		if (action>=0){	//sense
			reward = reward - CostM + CostS;
		}
		int movingDirection = action;
		if (map.brickStatus(xPosition, yPosition) == WorldMap.ICE){
			movingDirection = direction;
		}
		int nextX = xPosition;
		int nextY = yPosition;
		switch(movingDirection){
		case NORTH:
			if (map.isMovementBlocked(xPosition-1, yPosition)){
				nextX--;
			}
			break;
		case SOUTH:
			if (map.isMovementBlocked(xPosition+1, yPosition)){
				nextX++;
			}
			break;
		case EAST:
			if (map.isMovementBlocked(xPosition, yPosition+1)){
				nextY++;
			}
			break;
		case WEST:
			if (map.isMovementBlocked(xPosition, yPosition-1)){
				nextY--;
			}
			break;
		}


		boolean[] newFlags = Arrays.copyOf(flags, flags.length);
		Map<Node, Integer> newEvidence = new HashMap<Node, Integer>();
		int newDirection = NO_DIRECTION;
		newEvidence.putAll(evidence);

		int id = map.getFlagId(nextX, nextY);
		if (map.brickStatus(nextX, nextY)==WorldMap.FLAG && flags[id]){
			//flag reward
			reward += CopyOfMDPState.RewardF;
			newFlags[id] = false;
		}

		if (map.isIce(nextX, nextY)){
			//the block we are reaching is a potential ice block
			int cellNumber = map.getCellNumber(nextX,nextY);
			double iceProb = n.getProbIce(evidence, cellNumber);
			
			int newDirection2 = getNewDirection(nextX, nextY, movingDirection, map);
			
			Map<Node, Integer> newEvidence2 = new HashMap<Node, Integer>();
			newEvidence2.putAll(newEvidence);
			
			newEvidence.put(n.getBlockArr(cellNumber)[0], ClimateNetwork.NO_ICE);
			newEvidence2.put(n.getBlockArr(cellNumber)[0], ClimateNetwork.ICE);
			
			CopyOfMDPState m1 = new CopyOfMDPState(newFlags, nextX, nextY, newDirection, newEvidence, n);
			CopyOfMDPState m2 = new CopyOfMDPState(Arrays.copyOf(newFlags, newFlags.length), nextX, nextY, newDirection2, newEvidence2, n);
			ans.put(m1, (1-iceProb)*reward);
			ans.put(m2, iceProb*reward);

			//TODO - sensing alone
			//TODO - sensing when on ice
			//TODO for each possible ice block - if we dont have a second sensing for it - we need to add a node
		}
		if (action<=0){	//sensing

		}

		return null;
	}
	public int getNewDirection(int nextX, int nextY,int movingDirection, WorldMap map){
		int nextNextX = nextX;
		int nextNextY = nextY;
		switch(movingDirection){
		case NORTH:
			if (map.isMovementBlocked(xPosition-1, yPosition)){	nextNextX--;
			} break;
		case SOUTH:
			if (map.isMovementBlocked(xPosition+1, yPosition)){ nextNextX++;
			} break;
		case EAST:
			if (map.isMovementBlocked(xPosition, yPosition+1)){	nextNextY++;
			} break;
		case WEST:
			if (map.isMovementBlocked(xPosition, yPosition-1)){	nextNextY--;
			} break;
		}
		if (map.isMovementBlocked(nextNextX, nextNextY)){
			return NO_DIRECTION;
		} else {
			return movingDirection;
		}
	}

}
